#include <iostream>

#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/strings/str_format.h"

#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/health_check_service_interface.h>

#include "calc.ptoto.grpc.pb.h"

using namespace std;

// 定义命令行参数，服务器端口号，默认为 50051
ABSL_FLAG(uint16_t, port, 50051, "Server port for the service");

class CalcServiceImpl final : public calc::Calc::Service { // 继承并实现在helloworld.proto中定义的接口
    grpc::Status Add(grpc::ServerContext* context, const calc::AddRequest* request, calc::AddReply* reply) override {
        // 从request中取参数
        auto a = request->a();
        auto b = request->b();

        // 调用真正的处理逻辑，这里是简单的加法，ServiceImpl可以作为Proxy存在，持有一个业务对象的指针，然后调用相关的处理函数
        auto sum = a + b;

        // 设置reply中的字段作为返回值
        reply->set_sum(sum);
        return grpc::Status::OK;
    }
};

int main(int argc, char** argv) {
    // 解析命令行参数
    absl::ParseCommandLine(argc, argv);
    uint16_t port = absl::GetFlag(FLAGS_port);
    // 构建服务器地址字符串
    std::string server_address = absl::StrFormat("0.0.0.0:%d", port);

    // 创建服务实现对象
    CalcServiceImpl service;

    // 启用默认的健康检查服务和反射插件
    grpc::EnableDefaultHealthCheckService(true);
    grpc::reflection::InitProtoReflectionServerBuilderPlugin();
    // 创建服务器构建器
    grpc::ServerBuilder builder;

    // Listen on the given address without any authentication mechanism.
    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());

    // 注册服务实现对象到服务器构建器
    builder.RegisterService(&service);

    // 构建并启动服务器
    std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
    std::cout << "Server listening on " << server_address << std::endl;

    // 等待服务器关闭
    server->Wait();

    return 0;
}

